<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue组件基础示例</title>
    <!-- 引入Vue 3 -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        .demo-section {
            margin-bottom: 40px;
            padding: 20px;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            background-color: #f9f9f9;
        }
        .demo-section h2 {
            color: #42b983;
            border-bottom: 2px solid #42b983;
            padding-bottom: 10px;
            margin-top: 0;
        }
        .component-demo {
            margin: 20px 0;
            padding: 15px;
            background-color: #fff;
            border-radius: 4px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .code-block {
            background-color: #f4f4f4;
            padding: 15px;
            border-radius: 4px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            white-space: pre-wrap;
        }
        button {
            padding: 8px 16px;
            background-color: #42b983;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
        }
        button:hover {
            background-color: #3aa876;
        }
        .counter-display {
            font-size: 18px;
            font-weight: bold;
            margin: 10px 0;
        }
        .input-group {
            margin: 10px 0;
        }
        .input-group label {
            display: block;
            margin-bottom: 5px;
        }
        input {
            padding: 8px;
            width: 200px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        .user-card {
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin: 10px 0;
        }
        .highlight {
            color: #e74c3c;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <h1>Vue 3 组件基础</h1>
    
    <div class="demo-section">
        <h2>1. 全局组件</h2>
        <p>全局组件可以在任何Vue实例中使用</p>
        
        <div class="component-demo" id="app1">
            <global-greeting></global-greeting>
            <global-greeting name="Vue开发者"></global-greeting>
        </div>
        
        <div class="code-block">
// 定义全局组件
app.component('global-greeting', {
  props: ['name'],
  template: `
    <div>
      <h3>Hello, {{ name || '世界' }}!</h3>
      <p>这是一个全局组件</p>
    </div>
  `
})
        </div>
    </div>
    
    <div class="demo-section">
        <h2>2. 本地组件</h2>
        <p>本地组件需要在具体的Vue实例中注册后才能使用</p>
        
        <div class="component-demo" id="app2">
            <local-counter></local-counter>
        </div>
        
        <div class="code-block">
// 定义本地组件
const LocalCounter = {
  data() {
    return {
      count: 0
    }
  },
  template: `
    <div>
      <p class="counter-display">计数器: {{ count }}</p>
      <button @click="count++">增加</button>
      <button @click="count--">减少</button>
    </div>
  `
}

// 在Vue实例中注册本地组件
const app2 = Vue.createApp({
  components: {
    'local-counter': LocalCounter
  }
})
        </div>
    </div>
    
    <div class="demo-section">
        <h2>3. 组件的Props（属性）</h2>
        <p>Props允许父组件向子组件传递数据</p>
        
        <div class="component-demo" id="app3">
            <user-profile 
                :name="username" 
                :age="userAge"
                :is-vip="userIsVip"
            ></user-profile>
            
            <div class="input-group">
                <label>修改用户名:</label>
                <input v-model="username" />
            </div>
        </div>
        
        <div class="code-block">
// 带Props的组件
const UserProfile = {
  props: {
    name: {
      type: String,
      default: '游客'
    },
    age: {
      type: Number,
      default: 0
    },
    isVip: {
      type: Boolean,
      default: false
    }
  },
  template: `
    <div class="user-card">
      <h4>{{ name }} <span v-if="isVip" class="highlight">[VIP]</span></h4>
      <p>年龄: {{ age }}岁</p>
      <p>状态: {{ isVip ? '尊贵的VIP用户' : '普通用户' }}</p>
    </div>
  `
}

const app3 = Vue.createApp({
  components: {
    'user-profile': UserProfile
  },
  data() {
    return {
      username: '张三',
      userAge: 28,
      userIsVip: true
    }
  }
})
        </div>
    </div>
    
    <div class="demo-section">
        <h2>4. 组件的事件（自定义事件）</h2>
        <p>子组件可以通过自定义事件向父组件发送消息</p>
        
        <div class="component-demo" id="app4">
            <p>父组件收到的消息: <span class="highlight">{{ message }}</span></p>
            <message-sender @message-sent="handleMessage"></message-sender>
        </div>
        
        <div class="code-block">
// 发送自定义事件的组件
const MessageSender = {
  data() {
    return {
      inputMessage: ''
    }
  },
  template: `
    <div>
      <div class="input-group">
        <label>输入消息:</label>
        <input v-model="inputMessage" />
      </div>
      <button @click="sendMessage">发送消息给父组件</button>
    </div>
  `,
  methods: {
    sendMessage() {
      // 发送自定义事件，并传递数据
      this.$emit('message-sent', this.inputMessage)
      this.inputMessage = ''
    }
  }
}

const app4 = Vue.createApp({
  components: {
    'message-sender': MessageSender
  },
  data() {
    return {
      message: '等待消息...'
    }
  },
  methods: {
    handleMessage(msg) {
      this.message = msg
    }
  }
})
        </div>
    </div>
    
    <div class="demo-section">
        <h2>5. 组件的插槽（Slots）</h2>
        <p>插槽允许父组件向子组件传递HTML内容</p>
        
        <div class="component-demo" id="app5">
            <card-component>
              <template v-slot:header>
                <h3>卡片标题</h3>
              </template>
              
              <p>这是卡片的主要内容，可以包含任意HTML</p>
              <ul>
                <li>列表项 1</li>
                <li>列表项 2</li>
              </ul>
              
              <template v-slot:footer>
                <p>卡片底部信息</p>
              </template>
            </card-component>
        </div>
        
        <div class="code-block">
// 带插槽的组件
const CardComponent = {
  template: `
    <div class="user-card">
      <div class="card-header">
        <slot name="header">默认标题</slot>
      </div>
      <div class="card-body">
        <slot></slot> <!-- 默认插槽 -->
      </div>
      <div class="card-footer">
        <slot name="footer">默认底部</slot>
      </div>
    </div>
  `
}

const app5 = Vue.createApp({
  components: {
    'card-component': CardComponent
  }
})
        </div>
    </div>

    <script>
        // 示例1: 全局组件
        const app1 = Vue.createApp({})
        
        app1.component('global-greeting', {
          props: ['name'],
          template: `
            <div>
              <h3>Hello, {{ name || '世界' }}!</h3>
              <p>这是一个全局组件</p>
            </div>
          `
        })
        
        app1.mount('#app1')
        
        // 示例2: 本地组件
        const LocalCounter = {
          data() {
            return {
              count: 0
            }
          },
          template: `
            <div>
              <p class="counter-display">计数器: {{ count }}</p>
              <button @click="count++">增加</button>
              <button @click="count--">减少</button>
            </div>
          `
        }
        
        const app2 = Vue.createApp({
          components: {
            'local-counter': LocalCounter
          }
        })
        
        app2.mount('#app2')
        
        // 示例3: Props
        const UserProfile = {
          props: {
            name: {
              type: String,
              default: '游客'
            },
            age: {
              type: Number,
              default: 0
            },
            isVip: {
              type: Boolean,
              default: false
            }
          },
          template: `
            <div class="user-card">
              <h4>{{ name }} <span v-if="isVip" class="highlight">[VIP]</span></h4>
              <p>年龄: {{ age }}岁</p>
              <p>状态: {{ isVip ? '尊贵的VIP用户' : '普通用户' }}</p>
            </div>
          `
        }
        
        const app3 = Vue.createApp({
          components: {
            'user-profile': UserProfile
          },
          data() {
            return {
              username: '张三',
              userAge: 28,
              userIsVip: true
            }
          }
        })
        
        app3.mount('#app3')
        
        // 示例4: 自定义事件
        const MessageSender = {
          data() {
            return {
              inputMessage: ''
            }
          },
          template: `
            <div>
              <div class="input-group">
                <label>输入消息:</label>
                <input v-model="inputMessage" />
              </div>
              <button @click="sendMessage">发送消息给父组件</button>
            </div>
          `,
          methods: {
            sendMessage() {
              this.$emit('message-sent', this.inputMessage)
              this.inputMessage = ''
            }
          }
        }
        
        const app4 = Vue.createApp({
          components: {
            'message-sender': MessageSender
          },
          data() {
            return {
              message: '等待消息...'
            }
          },
          methods: {
            handleMessage(msg) {
              this.message = msg
            }
          }
        })
        
        app4.mount('#app4')
        
        // 示例5: 插槽
        const CardComponent = {
          template: `
            <div class="user-card">
              <div class="card-header">
                <slot name="header">默认标题</slot>
              </div>
              <div class="card-body">
                <slot></slot>
              </div>
              <div class="card-footer">
                <slot name="footer">默认底部</slot>
              </div>
            </div>
          `
        }
        
        const app5 = Vue.createApp({
          components: {
            'card-component': CardComponent
          }
        })
        
        app5.mount('#app5')
    </script>
</body>
</html>